<template>
    <n-data-table :key="(row: DataTable.TableData) => row.key" :columns="columns" :data="props.data"
        :pagination="paginationRef" :on-update:page="handlePageChange" scroll-x="1000" max-height="calc(100vh - 260px)" />
</template>
  
<script setup lang="ts">
import { h, defineComponent, ref, nextTick, computed } from 'vue'
import { NButton, NInput } from 'naive-ui'
import { TableColumn } from 'naive-ui/es/data-table/src/interface'


const emit = defineEmits<{
    (event: 'save-data', carInfo: DataTable.TableData): void
    (event: 'delete-data', index: number): void
}>()
const props = defineProps({
    data: {
        type: Array as PropType<DataTable.TableData[]>,
        default: [],
    },
    columns: {
        type: Array as PropType<DataTable.ColumnType[]>,
        default: [],
    }
})

const isEditRowList = ref<{ [rowIndex: number]: boolean }>({})

const page = ref<number>(1)
const paginationRef = computed<{ pageSize: number, page: number }>(() => ({
    pageSize: 10,
    page: page.value
}))

function isEdit(rowIndex: number) {
    return isEditRowList.value[rowIndex] || false
}
const ShowOrEdit = defineComponent({
    props: {
        value: [String, Number],
        rowIndex: Number,
        onUpdateValue: Function
    },
    setup(props) {
        const inputRef = ref<HTMLElement | null>(null)
        const inputValue = ref(props.value)
        function handleOnClick() {
            nextTick(() => {
                inputRef.value?.focus()
            })
        }
        function handleChange() {
            if (typeof props.onUpdateValue !== 'undefined') {
                props.onUpdateValue(inputValue.value)
            }
        }
        return () =>
            h(
                'div',
                {
                    style: 'min-height: 22px',
                    onClick: handleOnClick
                },
                isEdit(props.rowIndex as number)
                    ? h(NInput as any, {
                        ref: inputRef,
                        value: inputValue.value,
                        onUpdateValue: (v: string | number) => {
                            inputValue.value = v
                        },
                        onChange: handleChange
                    })
                    : props.value
            )
    }
})

function getDataIndex(key: string | number) {
    return props.data.findIndex((item) => item.key === key)
}
function handlePageChange(curPage: number) {
    page.value = curPage
    isEditRowList.value = []
}

const columns: Array<TableColumn> = (props.columns.map((item: DataTable.ColumnType, index: number) => ({
    key: item.key,
    title: item.title || item.key,
    width: index === props.columns.length ? undefined : (item.width || 150),
    render(row: DataTable.TableData) {
        const dataIndex = getDataIndex(row.key)
        return h(ShowOrEdit, {
            value: row[item.key],
            rowIndex: dataIndex % paginationRef.value.pageSize,
            onUpdateValue(v: any) {
                props.data[dataIndex][item.key] = v
            }
        })
    }
})) as any).concat([{
    key: 'operate',
    title: '操作',
    className: 'operate-column',
    fixed: 'right',
    width: 160,
    render(row: DataTable.TableData, rowIndex: number) {
        return h('div', { class: 'flex justify-evenly' },
            [h(NButton as any, {
                strong: true,
                secondary: true,
                type: isEdit(rowIndex) ? 'success' : 'primary',
                onClick: () => {
                    const index: number = getDataIndex(row.key)
                    if (isEdit(rowIndex)) {
                        emit('save-data', { ...props.data[index], key: index })
                        isEditRowList.value[rowIndex] = false
                    } else {
                        isEditRowList.value[rowIndex] = true
                    }
                }
            }, { default: () => isEdit(rowIndex) ? '保存' : '编辑' }), h(NButton as any, {
                strong: true,
                secondary: true,
                type: 'error',
                onClick: () => {
                    const index: number = getDataIndex(row.key)
                    emit('delete-data', index)
                    props.data.splice(index, 1)
                }
            }, { default: () => '删除' })])
    }
}])
</script>

<style lang="scss">
.operate-column .n-data-table-th__title {
    text-align: center;
}
</style>